<!--
* Listing_JS_Matrix.html
*
* Copyright © 2023 vetal .
*
* This file is part of JS_3D.
*
* JS_3D is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* JS_3D is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with JS_3D. If not, see <http ://www.gnu.org/licenses/>.
*/-->


<!DOCTYPE html>
<html>
<body onload="loadEnv()" onkeydown="onKeyDown(event)">
<script src="points.js"></script>
<script>

var ctx;
var screen_width = 600;
var screen_height = 600;
var mainInterval;

var n = 0.10;
var w = 0.20;
var h = 0.20;
var f = 10.0;

var tr = [0,0,-4];
var angle = 0;

//var points = [];

function onKeyDown(event) {
  if(event.key == "w")
    tr[2] += -0.5;
  else if(event.key == "s")
    tr[2] += 0.5;
}

function transv(v) {
  v[0] += tr[0];
  v[1] += tr[1];
  v[2] += tr[2];
}

function rotyv(v) {
  var t = [0,0,0];
  t[0] = v[0]*Math.cos(angle) + v[2]*Math.sin(angle);
  t[2] = -v[0]*Math.sin(angle) + v[2]*Math.cos(angle);
  v[0] = t[0];
  v[2] = t[2];
}

function rotxv(v) {
  var t = [0,0,0];
  t[1] = v[1]*Math.cos(angle) - v[2]*Math.sin(angle);
  t[2] = v[1]*Math.sin(angle) + v[2]*Math.cos(angle);
  v[1] = t[1];
  v[2] = t[2];
}


function persv(v) {
  v[0] = 2*n*v[0]/(w*(-v[2]));
  v[1] = 2*n*v[1]/(h*(-v[2]));
  v[2] = (n+f)/(f-n) + 2*n*f/((f-n)*v[2]);
}

function toscreen(v) {
  v[0] = Math.floor(v[0]*screen_width/2 + screen_width/2);
  v[1] = Math.floor(-v[1]*screen_height/2 + screen_height/2);
}

function drawPoint(v) {
  ctx.fillStyle = "#FF0000";
  ctx.fillRect(v[0],v[1], 5, 5);
}

function drawTriangle(a,b,c) {
  ctx.beginPath();
  ctx.moveTo(a[0], a[1]);
  ctx.lineTo(b[0], b[1]);
  ctx.lineTo(c[0], c[1]);
  ctx.lineTo(a[0], a[1]);
  ctx.fill();
}

function loadEnv() {
  var canvas = document.createElement("canvas");
  canvas.width = screen_width;
  canvas.height = screen_height;
  ctx = canvas.getContext("2d");
  document.body.insertBefore(canvas, document.body.childNodes[0]);

  mainInterval = setInterval(mainLoop, 10);

}

function ortov(a,b,c,v) {
  var v1 = [b[0]-a[0], b[1]-a[1], b[2]-a[2]];
  var v2 = [c[0]-b[0], c[1]-b[1], c[2]-b[2]];
  v[0] = v1[1]*v2[2]-v2[1]*v1[2];
  v[1] = v2[0]*v1[2]-v1[0]*v2[2];
  v[2] = v1[0]*v2[1]-v2[0]*v1[1];
}

function normalizev(v) {
  var d = Math.sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
  v[0] /= d;
  v[1] /= d;
  v[2] /= d;
};

function scalarv(a,b) {
  return a[0]*b[0]+a[1]*b[1]+a[2]*b[2];
}


function mainLoop() {
  ctx.fillStyle = "#000000";
  ctx.fillRect(0, 0, screen_width, screen_height);
  var pcount = Math.floor(points.length/9);
  var a = [0,0,0];
  var b = [0,0,0];
  var c = [0,0,0];
  angle += 0.01;
  for(var i=0; i<pcount; i++) {
    a[0] = points[9*i];
    a[1] = points[9*i+1];
    a[2] = points[9*i+2];

    b[0] = points[9*i+3];
    b[1] = points[9*i+4];
    b[2] = points[9*i+5];

    c[0] = points[9*i+6];
    c[1] = points[9*i+7];
    c[2] = points[9*i+8];


    rotxv(a);
    rotyv(a);
    transv(a);

    rotxv(b);
    rotyv(b);
    transv(b);

    rotxv(c);
    rotyv(c);
    transv(c);

    var ca = [a[0], a[1], a[2]];
    var ort = [0,0,0];
    ortov(a,b,c,ort);
    normalizev(ort);
    normalizev(ca);
    var sc = scalarv(ca, ort);

    persv(a);
    toscreen(a);
    persv(b);
    toscreen(b);
    persv(c);
    toscreen(c);

    if(sc < 0) {
      var num = Math.floor(-sc*256) % 256;
      num = num.toString(16);
      if(num.length == 1) num = "0" + num;
      ctx.fillStyle = "#" + num + num + num;
      drawTriangle(a,b,c);
    };

  }
}

</script>
</body>
</html>
